package com.todod.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.todod.common.util.Doc2PdfUtil;
import com.todod.common.util.MinIoUtils;
import com.todod.common.util.Result;
import com.todod.common.util.SnowflakeIdGenerator;
import com.todod.dto.ProjectFileDto;
import com.todod.entity.QueryProjectFile;
import com.todod.exception.UploadFileException;
import com.todod.mapper.ProjectFileMapper;
import com.todod.model.ProjectFile;
import com.todod.model.ProjectFileEvaluate;
import com.todod.model.User;

/**
 * @param
 * @author dyl
 * @date 2021-03-16
 */
@Service
@Transactional
public class ProjectFileService {

	@Value("${file.upload.path}")
	private String uploadPath;
	@Value("${file.upload.mapping}")
	private String showPath;
	@Value("${file.visit}")
	private String visi;
	@Autowired
	private ProjectFileMapper projectFileMapper;
	@Autowired
	private IUserService iUserService;

	Logger log = LoggerFactory.getLogger(this.getClass());
	@Autowired
	public ProjectFileEvaluateService projectFileEvaluateService;

	// 存储桶名称
	@Value("${minio.bucketName}")
	private String bucketName;
	@Autowired
	private MinIoUtils minIoUtils;
	// allowed minimum part size is 5MiB in multipart upload.
	public static final int MIN_MULTIPART_SIZE = 5 * 1024 * 1024;

	/**
	 * 
	 * @param _userId
	 * @param queryProjectFile
	 * @return
	 */
	public IPage<ProjectFileDto> getListPage(Long _userId, QueryProjectFile queryProjectFile) {
		Page<ProjectFileDto> page = new Page<>(queryProjectFile.getPage(), queryProjectFile.getLimit());

		IPage<ProjectFileDto> iPage = projectFileMapper.getListPage(page, _userId, queryProjectFile);

		List<ProjectFileDto> records = iPage.getRecords();
		for (ProjectFileDto record : records) {
			User user = iUserService.getById(record.getCreateuserId());

			if (!_userId.equals(user.getId())) {// 判断登录人与创建人是否一致
				record.setIsEdit("1");
				List<ProjectFileEvaluate> list = projectFileEvaluateService.getEvaluateListByFileId(record.getId());
				if (list != null && list.size() > 0) {
					record.setIsEdit("3");
				}
			} else {
				record.setIsEdit("2");
			}
			record.setCreateuserName(user.getNickName());
		}

		return iPage;
	}

	/**
	 * 
	 * @param _userId
	 * @param request
	 * @param xftId
	 * @param xiangmuId
	 * @param companyId
	 * @param batchCode
	 * @return
	 */
	public ProjectFile saveUploadFile(Long _userId, HttpServletRequest request, Long xftId, Long xiangmuId,
			Long companyId, String batchCode) {
//		String relativePath = null, docPath = null, pdfPath = null;
		ProjectFile projectFile = null;
		FileInputStream fis = null;
		try {

			MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
			MultipartFile uploadFile = req.getFile("uploadfile_ant");// 返回上传文件的内容和描述
			String originalName = uploadFile.getOriginalFilename();
			String file_ext_name = originalName.substring(originalName.lastIndexOf(".") + 1);

			log.info("开始上传-----------------------------------------{}", originalName);
			String relativePath = minIoUtils.upload(uploadFile, bucketName, null);
			log.info("上传结束-----------------------------------------{}", relativePath);

//			if (file_ext_name.equalsIgnoreCase("docx") || file_ext_name.equalsIgnoreCase("doc")) {
//
//				String pdfName = UUID.randomUUID().toString() + ".pdf";
//				String path = uploadPath + File.separator + "static" + File.separator + "file" + File.separator
//						+ "yulan";
//				String relativePath1 = uploadPath + "/" + "static" + "/" + "file" + "/" + "yulan";
//
//				docPath = path + File.separator + originalName;
//				pdfPath = relativePath1 + File.separator + pdfName;
//
//				File dir = new File(path);
//				if (!dir.exists()) {
//					dir.mkdirs();
//				}
//
//				FileCopyUtils.copy(uploadFile.getInputStream(), new FileOutputStream(docPath));
//
//				log.info("开始转换docPath=-----------------------------------------{}", docPath);
//				log.info("开始转换pdfPath=-----------------------------------------{}", pdfPath);
//				Doc2PdfUtil.word2Pdf(docPath, pdfPath);
//				log.info("转换完成-----------------------------------------{}", pdfPath);
//			}

			projectFile = new ProjectFile();
			projectFile.setId(SnowflakeIdGenerator.getId());

			projectFile.setBatchCode(batchCode);
			projectFile.setDepartmentId(companyId);
			projectFile.setXftId(xftId);
			projectFile.setXiangmuId(xiangmuId);
			projectFile.setOriginalName(originalName);
			projectFile.setFileName(relativePath);
			projectFile.setSuffix(file_ext_name);
			projectFile.setFileSize(uploadFile.getSize());
			projectFile.setAbstractPath(visi + relativePath);
			projectFile.setRelativePath(relativePath);

//			if (pdfPath != null) {
//				// 文件上传参数1：需要上传文件的绝字节数组 参数2：上传文件的扩展名 参数3：文件的属性文件一般不上传
//				fis = new FileInputStream(pdfPath);
//
//				File tofile = new File(docPath);
//				File tofile1 = new File(pdfPath);
//
//				String yulanPath = minIoUtils.newUpload(bucketName, tofile1.getName(), fis, "application/pdf");
//
//				projectFile.setYulanPath(visi + yulanPath);
//				if (tofile.exists()) {
//					tofile.delete();
//				}
//				if (tofile1.exists()) {
//					tofile1.delete();
//				}
//			}

//			List<ProjectFile> list = selectByXftId(projectFile.getXftId(), projectFile.getXiangmuId(),
//					projectFile.getOriginalName());
//			if (list.size() > 0) {
//				projectFile.setSortNum(list.size() + 1);
//				projectFile.setBatchCode(list.get(0).getBatchCode());
//
//				for (ProjectFile projectFile1 : list) {
//					projectFile1.setState("2");
//					projectFile1.setModifyuserId(_userId);
//					projectFile1.setModifytimeTi(LocalDateTime.now());
//					projectFileMapper.updateById(projectFile1);
//				}
//			} else {
//				projectFile.setSortNum(1);
//			}

//			projectFileMapper.insert(projectFile);
		} catch (Exception e) {
			log.error("file_upload", e);
			throw new UploadFileException("上传文件失败");
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return projectFile;
	}

	/**
	 * 
	 * @param _userId
	 * @param projectFile
	 */
	public void saveData(Long _userId, ProjectFile projectFile) {

//		List<ProjectFile> list = projectFileMapper.selectByXftId(xftId, xiangmuId, batchCode);
		List<ProjectFile> list = selectByXftId(projectFile.getXftId(), projectFile.getXiangmuId(),
				projectFile.getOriginalName());
		if (list.size() > 0) {
			projectFile.setSortNum(list.size() + 1);
			projectFile.setBatchCode(list.get(0).getBatchCode());

			for (ProjectFile projectFile1 : list) {
				projectFile1.setState("2");
				projectFile1.setModifyuserId(_userId);
				projectFile1.setModifytimeTi(LocalDateTime.now());
				projectFileMapper.updateById(projectFile1);
			}
		} else {
			projectFile.setSortNum(1);
		}

//		ProjectFile projectFile1 = projectFileMapper.selectById(projectFile.getId());

		projectFile.setState("1");
		projectFile.setCreateuserId(_userId);
		projectFile.setCreatetimeTi(LocalDateTime.now());
//		projectFileMapper.updateById(projectFile1);
		projectFileMapper.insert(projectFile);
	}

	/**
	 * 
	 * @param _userId
	 * @param projectFile
	 */
	public void editData(Long _userId, ProjectFile projectFile) {

		ProjectFile projectFile1 = projectFileMapper.selectById(projectFile.getId());

		projectFile1.setState("2");
		projectFile1.setCreateuserId(projectFile1.getCreateuserId());
		projectFile1.setCreatetimeTi(projectFile1.getCreatetimeTi());
		projectFile1.setModifyuserId(_userId);
		projectFile1.setModifytimeTi(LocalDateTime.now());
		projectFileMapper.updateById(projectFile1);

		projectFile.setId(SnowflakeIdGenerator.getId());
		projectFile.setSortNum(projectFile1.getSortNum() + 1);
		projectFile.setState("1");
		projectFile.setBatchCode(projectFile1.getBatchCode());
		projectFile.setCreateuserId(_userId);
		projectFile.setCreatetimeTi(LocalDateTime.now());
		projectFileMapper.insert(projectFile);
	}

	/**
	 * 
	 * @param xftId
	 * @return
	 */
	public List<ProjectFile> getListByXftId(Long xftId) {

		QueryWrapper<ProjectFile> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("xf_xft_id", xftId);

		List<ProjectFile> list = projectFileMapper.selectList(queryWrapper);

		return list;
	}

	/**
	 * 
	 * @param _userId
	 * @param queryProjectFile
	 * @return
	 */
	public IPage<ProjectFileDto> getSPListPage(Long _userId, QueryProjectFile queryProjectFile) {
		Page<ProjectFileDto> page = new Page<>(queryProjectFile.getPage(), queryProjectFile.getLimit());

		IPage<ProjectFileDto> iPage = projectFileMapper.getSPListPage(page, _userId, queryProjectFile);

		List<ProjectFileDto> records = iPage.getRecords();
		for (ProjectFileDto record : records) {
			User user = iUserService.getById(record.getCreateuserId());

			if (!_userId.equals(user.getId())) {// 判断登录人与创建人是否一致
				record.setIsEdit("1");
			} else {
				record.setIsEdit("2");
			}
			record.setCreateuserName(user.getNickName());
		}

		return iPage;
	}

	/**
	 * 
	 * @param request
	 * @param image
	 * @return
	 */
	public ProjectFile saveUpload(HttpServletRequest request, MultipartFile image) {
//		TrackerServer trackerServer = null;
		String relativePath = null;
		ProjectFile projectFile = null;
		try {

			String originalName = image.getOriginalFilename();
//			byte[] file_buff = image.getBytes();
			String file_ext_name = originalName.substring(originalName.lastIndexOf(".") + 1);

//			trackerServer = trackerClient.getConnection();
//
//			StorageClient storageClient = new StorageClient(trackerServer, null);
//			// 文件上传参数1：需要上传文件的绝字节数组 参数2：上传文件的扩展名 参数3：文件的属性文件一般不上传
//			String[] result = storageClient.upload_file("knowledge", file_buff, file_ext_name, null);
//			String fileName = result[1].substring(result[1].lastIndexOf("/") + 1);
//			relativePath = "/" + result[0] + "/" + result[1];

			relativePath = minIoUtils.upload(image, bucketName, null);

			projectFile = new ProjectFile();
			projectFile.setId(SnowflakeIdGenerator.getId());

			projectFile.setBatchCode("1");
			projectFile.setDepartmentId(1l);
			projectFile.setXftId(1l);
			projectFile.setXiangmuId(1l);
			projectFile.setOriginalName(originalName);
			projectFile.setFileName(relativePath);
			projectFile.setSuffix(file_ext_name);
			projectFile.setFileSize(image.getSize());
			projectFile.setAbstractPath(visi + relativePath);
			projectFile.setRelativePath(relativePath);

			projectFile.setSortNum(1);

			projectFile.setCreateuserId(1l);
			projectFile.setCreatetimeTi(LocalDateTime.now());

		} catch (Exception e) {
			log.error("file_upload", e);
			throw new UploadFileException("上传文件失败");
		}

		return projectFile;
	}

	/**
	 * 
	 * @param originalName
	 * @return
	 */
	public boolean getFileByFileName(Long xftId, String originalName) {
		QueryWrapper<ProjectFile> queryWrapper = new QueryWrapper<>();
//		queryWrapper.eq("xf_xft_id", xftId);
		queryWrapper.eq("xf_original_name", originalName);

		List<ProjectFile> list = projectFileMapper.selectList(queryWrapper);
		if (list.size() > 0) {
			return true;
		} else {
			return false;
		}
	}

	public List<ProjectFile> getListFileByParentId(Long xftId) {
		QueryWrapper<ProjectFile> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("xf_xft_id", xftId);
		queryWrapper.orderByAsc("xf_sort_num");
		return projectFileMapper.selectList(queryWrapper);
	}

	public List<ProjectFile> getListByParentIdAndXftId(Long xiangmuId, Long xftId) {
		QueryWrapper<ProjectFile> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("xf_xft_id", xftId);
		queryWrapper.eq("xf_xiangmu_id", xiangmuId);
		queryWrapper.eq("xf_state", "1");
		queryWrapper.orderByAsc("xf_sort_num");
		return projectFileMapper.selectList(queryWrapper);
	}

	private List<ProjectFile> selectByXftId(Long xftId, Long xiangmuId, String originalName) {
		QueryWrapper<ProjectFile> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("xf_original_name", originalName);
		queryWrapper.eq("xf_xft_id", xftId);
		queryWrapper.eq("xf_xiangmu_id", xiangmuId);
//		queryWrapper.eq("xf_state", "1");
		queryWrapper.orderByAsc("xf_sort_num");
		return projectFileMapper.selectList(queryWrapper);
	}

	public ProjectFile selectByXftId(Long xftId, String originalName) {
		QueryWrapper<ProjectFile> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("xf_original_name", originalName);
		queryWrapper.eq("xf_xft_id", xftId);
		queryWrapper.eq("xf_state", "1");
		queryWrapper.orderByAsc("xf_sort_num");
		return projectFileMapper.selectOne(queryWrapper);
	}

	/**
	 * 单文件分片上传 直接将传入的文件分片通过io流形式写入(服务器)指定临时路径下
	 * 然后判断是否分片都上传完成，如果所有分片都上传完成的话，就把临时路径下的分片文件通过流形式读入合并并从新写入到(服务器)指定文件路径下
	 * 最后删除临时文件和临时文件夹，临时文件夹是通过文件的uuid进行命名的
	 *
	 * @param filePart  分片文件
	 * @param partIndex 当前分片值
	 * @param partNum   所有分片数
	 * @param fileName  当前文件名称
	 * @param fileUid   当前文件uuid
	 * @param fileSize
	 * @return
	 */
	public Result<Boolean> singleFilePartUpload(MultipartFile filePart, Integer partIndex, Integer partNum,
			String fileName, String fileUid, Long fileSize) {

		FileInputStream fis = null;
		String relativePath = "";
		// 实际情况下，这些路径都应该是服务器上面存储文件的路径
		String filePath = uploadPath + File.separator + "static" + File.separator + "file" + File.separator + "temp"
				+ File.separator + fileUid;// 文件存放路径
		File tempDir = new File(filePath);
		if (!tempDir.exists())
			tempDir.mkdirs();

		if (fileSize > MIN_MULTIPART_SIZE) {
			// 生成一个临时文件名
			String tempFileNamePath = filePath + "\\" + fileName + "_" + partIndex + ".part";
			try {
				// 将分片存储到临时文件夹中
				filePart.transferTo(new File(tempFileNamePath));

				fis = new FileInputStream(tempFileNamePath);

				minIoUtils.newUpload(bucketName, fileName + "_" + partIndex + ".part", fis, filePart.getContentType(),
						fileUid);

				relativePath = minIoUtils.uploadFileComplete("crawler", fileUid, fileName, partNum,
						filePart.getContentType(), tempDir, filePath);

			} catch (Exception e) {
				log.error("单文件分片上传失败!", e);
			}
		} else {
			// 生成一个临时文件名
			String tempFileNamePath = filePath + "\\" + fileName;
			try {
				// 将分片存储到临时文件夹中
				filePart.transferTo(new File(tempFileNamePath));

				fis = new FileInputStream(tempFileNamePath);

				relativePath = minIoUtils.newUpload(bucketName, fileName, fis, filePart.getContentType());

				if (relativePath != null && StringUtils.isNotBlank(relativePath)) {
					// 删除临时文件夹里面的分片文件 如果使用流操作且没有关闭输入流，可能导致删除失败
					for (int i = 0; i < partNum; i++) {
						new File(filePath + "\\" + fileName).delete();
					}
					// 在删除对应的临时文件夹
					tempDir.delete();
				}
			} catch (Exception e) {
				log.error("文件上传失败!", e);
			}
		}
		// 通过返回成功的分片值，来验证分片是否有丢失
		return Result.success(true, partIndex.toString(), relativePath);
	}

	public ProjectFile saveUploadFile(Long _userId, MultipartFile uploadFile, Long xftId, Long xiangmuId, Long departid,
			String batchCode) {
//		String relativePath = null, docPath = null, pdfPath = null;
		ProjectFile projectFile = null;
		FileInputStream fis = null;
		try {

			String originalName = uploadFile.getOriginalFilename();
			String file_ext_name = originalName.substring(originalName.lastIndexOf(".") + 1);

			String relativePath = minIoUtils.upload(uploadFile, bucketName, null);

			projectFile = new ProjectFile();
			projectFile.setId(SnowflakeIdGenerator.getId());

			projectFile.setBatchCode(batchCode);
			projectFile.setDepartmentId(departid);
			projectFile.setXftId(xftId);
			projectFile.setXiangmuId(xiangmuId);
			projectFile.setOriginalName(originalName);
			projectFile.setFileName(relativePath);
			projectFile.setSuffix(file_ext_name);
			projectFile.setFileSize(uploadFile.getSize());
			projectFile.setAbstractPath(visi + relativePath);
			projectFile.setRelativePath(relativePath);

		} catch (Exception e) {
			log.error("file_upload", e);
			throw new UploadFileException("上传文件失败");
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return projectFile;
	}

	public void saveNewData(Long _userId, ProjectFile projectFile) {
		List<ProjectFile> list = selectByXftId(projectFile.getXftId(), projectFile.getXiangmuId(),
				projectFile.getOriginalName());
		if (list.size() > 0) {
			projectFile.setSortNum(list.size() + 1);
			projectFile.setBatchCode(list.get(0).getBatchCode());

			for (ProjectFile projectFile1 : list) {
				projectFile1.setState("2");
				projectFile1.setModifyuserId(_userId);
				projectFile1.setModifytimeTi(LocalDateTime.now());
				projectFileMapper.updateById(projectFile1);
			}
		} else {
			projectFile.setSortNum(1);
		}

		projectFile.setId(SnowflakeIdGenerator.getId());

		String file_ext_name = projectFile.getRelativePath()
				.substring(projectFile.getRelativePath().lastIndexOf(".") + 1);

		projectFile.setDepartmentId(1l);
		projectFile.setFileName(projectFile.getRelativePath());
		projectFile.setSuffix(file_ext_name);
		projectFile.setAbstractPath(visi + projectFile.getRelativePath());
		projectFile.setRelativePath(projectFile.getRelativePath());

		projectFile.setState("1");

		projectFile.setCreateuserId(1l);
		projectFile.setCreatetimeTi(LocalDateTime.now());

		projectFileMapper.insert(projectFile);
	}

	public Result<Boolean> singleFilePartUpload2(MultipartFile filePart, Integer partIndex, Integer partNum,
			String fileName, String fileUid) {
		// 实际情况下，这些路径都应该是服务器上面存储文件的路径
		String filePath = uploadPath + File.separator + "static" + File.separator + "file" + File.separator + "temp"
				+ File.separator + fileUid;// 文件存放路径
		File tempDir = new File(filePath);
		if (!tempDir.exists())
			tempDir.mkdirs();

		// 生成一个临时文件名
		String tempFileNamePath = null;
		String pdfPath = null;
		String file_ext_name = fileName.substring(fileName.lastIndexOf(".") + 1);
		if (file_ext_name.equalsIgnoreCase("docx") || file_ext_name.equalsIgnoreCase("docx")) {
			tempFileNamePath = filePath + "\\" + fileName + "_" + partIndex + "." + file_ext_name + "";
		} else {
			tempFileNamePath = filePath + "\\" + fileName + "_" + partIndex + ".part";
		}

		try {
			// 将分片存储到临时文件夹中
			filePart.transferTo(new File(tempFileNamePath));

			if (file_ext_name.equalsIgnoreCase("docx") || file_ext_name.equalsIgnoreCase("doc")) {

				pdfPath = filePath + File.separator + fileName + "_" + partIndex + ".pdf";

				log.info("开始转换docPath=-----------------------------------------{}", tempFileNamePath);
				log.info("开始转换pdfPath=-----------------------------------------{}", pdfPath);
				Doc2PdfUtil.word2Pdf(tempFileNamePath, pdfPath);
				log.info("转换完成-----------------------------------------{}", pdfPath);
			}

		} catch (Exception e) {
			log.error("单文件分片上传失败!", e);
		}
		// 通过返回成功的分片值，来验证分片是否有丢失
		return Result.success(true, partIndex.toString());
	}

}
